/*-
 * ProjectJpaRepository.java
 *
 * Date: 2016年4月29日
 * Time: 下午3:50:44
 *
 * 版权所有©2012-2013 rengh
 */

package com.lmx.persistence.service.common;

import java.io.File;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.lmx.common.constants.ICommonConstants;
import com.lmx.common.context.ActionContextHolder;
import com.lmx.common.util.CommonUtil;
import com.lmx.common.util.ExcelExport;
import com.lmx.common.util.URLUtil;
import com.lmx.persistence.dao.GenericDao;
import com.lmx.persistence.service.GenericService;
import com.lmx.repoDomain.exception.BusinessException;
import com.lmx.repoDomain.tmodel.BaseDataEntity;
import com.lmx.repoDomain.tmodel.Identifiable;
import com.lmx.repoDomain.tmodel.PageInfo;
import com.lmx.repoDomain.tmodel.Tenant;
import com.lmx.repoDomain.tmodel.unpersis.ExportParam;
import com.lmx.repoDomain.tmodel.unpersis.ExportStatusEnum;
import com.lmx.repoDomain.tmodel.unpersis.ExportThreadParam;
import com.lmx.repoDomain.tmodel.unpersis.POIParam;
import com.querydsl.core.types.Order;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.PathExtractor;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.PathBuilder;
import com.querydsl.jpa.HQLTemplates;
import com.querydsl.jpa.impl.JPAQuery;

import io.katharsis.queryParams.QueryParams;
import io.katharsis.queryParams.RestrictedPaginationKeys;
import io.katharsis.queryParams.include.Inclusion;
import io.katharsis.queryParams.params.IncludedRelationsParams;
import io.katharsis.queryParams.params.SortingParams;
import io.katharsis.queryParams.params.TypedParams;

/**
 * #{description}
 *
 * @author Administrator
 * @version 1.00
 */
@Service
@Scope("prototype")
public class DslJpaService<T extends BaseDataEntity> extends AbstractService
		implements GenericService {
	private Log logger = LogFactory.getLog(this.getClass());

	@PersistenceContext
	private EntityManager em;
	private Class entityClass = null;

	@Override
	public Identifiable findById(final Long id) {
		return (Identifiable) this.getDao().findOne(id);
	}

	public void detach(final Object entity) {
		em.detach(entity);
	}

	public void remove(final Object entity) {
		this.getDao().delete(entity);
	}

	public List<T> findAll(final Predicate expr) {
		final Class<T> clazz = this.getEntityClass();
		final Path<?> path = expr.accept(PathExtractor.DEFAULT, null);
		final PathBuilder<?> builder = new PathBuilder<T>(clazz, "entity");
		final JPAQuery query = new JPAQuery(em);
		query.from(builder).where(expr);
		new JPAQuery<>(em, HQLTemplates.DEFAULT);
		return query.fetch();
	}

	private JPAQuery buildQuery(final QueryParams requestParams) {
		final Class<T> clazz = this.getEntityClass();
		final PathBuilder<?> builder = new PathBuilder<T>(clazz, "entity");
		BooleanExpression predicate = buildPredicate(builder, requestParams);
		final JPAQuery query = new JPAQuery(em);
		query.from(builder);
		// 拼接关联查询
		ArrayList<String> joinList = getJoinCloumn(builder, requestParams);
		for (int i = 0; i < joinList.size(); i++) {
			PathBuilder<?> pathBuilder = new PathBuilder(Object.class,
					"entity." + joinList.get(i));
			Path alias = new PathBuilder(Object.class, joinList.get(i));
			// 通过fetchJoin来带出关联表数据
			query.leftJoin(pathBuilder, alias).fetchJoin();
			BooleanExpression texp = pathBuilder.getNumber("delStatus",
					Long.class).eq((long) 0);
			predicate = predicate.and(texp);// huibati 删除判断
		}
		query.where(predicate);

		// 分页
		Map<RestrictedPaginationKeys, Integer> pagintion = requestParams
				.getPagination();// 获取分页参数
		if (pagintion.size() > 0
				&& setPageInfo(query, builder, predicate, requestParams)) { // 判断是否需要分页
			query.offset(PageInfo.getInstance().getStartNum() - 1).limit(
					PageInfo.getInstance().getSize());
		}
		/*
		 * else{
		 *//*
			 * PathBuilder<?> taskTypesPath = new PathBuilder(Object.class,
			 * "entity.taskTypes"); Path taskTypesAlias = new
			 * PathBuilder(Object.class, "taskTypes"); PathBuilder<?>
			 * taskTypesBuilder = new PathBuilder(Object.class, "taskTypes");
			 * BooleanExpression predicateChange =
			 * predicate.and(taskTypesBuilder.get("id").eq(1));
			 * query.from(builder).leftJoin(taskTypesPath,
			 * taskTypesAlias).fetchJoin(); query.where(predicateChange);
			 *//*
				 * //
				 * query.from(builder).leftJoin(taskTypesPath,taskTypesAlias).
				 * fetchJoin().where(predicateChange);
				 * query.from(builder).where(predicate); }
				 */
		// 排序
		TypedParams<SortingParams> sortParams = requestParams.getSorting();
		Map<String, SortingParams> sortMap = sortParams.getParams();
		if (sortMap.size() > 0) { // 判断是否排序
			ArrayList<OrderSpecifier> orderSpecifiers = getOrderSpecifiers(
					sortMap, builder);
			for (int i = 0; i < orderSpecifiers.size(); i++) {
				query.orderBy(orderSpecifiers.get(i));
			}
		}
		return query;
	}

	@Override
	public Iterable<T> findAll(final QueryParams requestParams) {
		final JPAQuery query = this.buildQuery(requestParams);
		query.distinct();
		// query.exists();
		query.setHint("org.hibernate.cacheable", true);
		List list = query.fetch();
		return list;
	}

	@Override
	public Iterable<T> findAllBusi(final QueryParams requestParams,
			Long tenantId) {
		return this.findAllBusi(requestParams, tenantId, true);
	}

	@Override
	public Iterable<T> findAllBusi(final QueryParams requestParams,
			Long tenantId, Boolean page) {
		final Class<T> clazz = this.getEntityClass();
		final PathBuilder<?> builder = new PathBuilder<T>(clazz, "entity");
		BooleanExpression predicate = buildPredicate(builder, requestParams);
		final JPAQuery query = new JPAQuery(em);
		query.from(builder);
		// 拼接关联查询
		ArrayList<String> joinList = getJoinCloumn(builder, requestParams);
		for (int i = 0; i < joinList.size(); i++) {
			PathBuilder<?> pathBuilder = new PathBuilder(Object.class,
					"entity." + joinList.get(i));
			Path alias = new PathBuilder(Object.class, joinList.get(i));
			// 通过fetchJoin来带出关联表数据
			query.leftJoin(pathBuilder, alias).fetchJoin();
			BooleanExpression texp = ((PathBuilder) alias).getNumber(
					"delStatus", Long.class).eq((long) 0);
			predicate = predicate.and(texp);// 删除判断
		}

		// 添加租户id条件
		PathBuilder<?> tpathBuilder = new PathBuilder(Tenant.class,
				"entity.tenant");
		// 不查租户 条件
		logger.debug("clazz.getName():" + clazz.getSimpleName());
		if (clazz.getSimpleName().equals("Dicttype")
				|| clazz.getSimpleName().equals("Province")
				|| clazz.getSimpleName().equals("City")
				|| clazz.getSimpleName().equals("Town")
				|| clazz.getSimpleName().equals("County")
				|| clazz.getSimpleName().equals("Village")
				|| clazz.getSimpleName().equals("StatQueryType")
				|| clazz.getSimpleName().equals("TypegroupTenant")
				|| clazz.getSimpleName().equals("Tenant")
				|| clazz.getSimpleName().equals("DeviceTypeItem")
				|| clazz.getSimpleName().equals("ServiceFinishLevel")
				|| clazz.getSimpleName().equals("Conf")
				|| clazz.getSimpleName().equals("EvaluateModelType")
				|| clazz.getSimpleName().equals("EvaluateModel")
				|| clazz.getSimpleName().equals("EvaluateScoreScope")
				|| clazz.getSimpleName().equals("EvaluateAnswer")
				|| (clazz.getSimpleName().equals("Privilege") && tenantId < 1000)
				|| tenantId == null) {// 不关联租户查询
		} else {
			Path alias = new PathBuilder(Tenant.class, "tenant");
			query.leftJoin(tpathBuilder, alias);// .fetchAll();
			BooleanExpression texp = tpathBuilder.getNumber("id", Long.class)
					.eq(tenantId);
			predicate = predicate.and(texp);
		}
		// 验证删除标识 为0
		BooleanExpression texp2 = builder.getNumber("delStatus", Long.class)
				.eq((long) 0);
		predicate = predicate.and(texp2);
		query.where(predicate);

		// 一对多外链接查询的时候需要去重
		Map<String, String> fielter = CommonUtil
				.getKeyMapByFilter(requestParams);
		if (fielter.containsKey("oneToManyFlag")
				&& "1".equals(fielter.get("oneToManyFlag"))) {
			query.distinct();
		}

		if (page) {
			// 分页
			Map<RestrictedPaginationKeys, Integer> pagintion = requestParams
					.getPagination();// 获取分页参数
			if (pagintion.size() > 0
					&& setPageInfo(query, builder, predicate, requestParams)) { // 判断是否需要分页
				query.offset(PageInfo.getInstance().getStartNum() - 1);
				query.limit(PageInfo.getInstance().getSize());
			}
		}
		// 排序
		TypedParams<SortingParams> sortParams = requestParams.getSorting();
		Map<String, SortingParams> sortMap = sortParams.getParams();
		if (sortMap.size() > 0) { // 判断是否排序
			ArrayList<OrderSpecifier> orderSpecifiers = getOrderSpecifiers(
					sortMap, builder);
			for (int i = 0; i < orderSpecifiers.size(); i++) {
				query.orderBy(orderSpecifiers.get(i));
			}
		}
		query.setHint("org.hibernate.cacheable", true);
		List list = query.fetch();
		return list;
	}

	@Override
	public Iterable<T> export(QueryParams reQueryParams, Long tenantId,
			ExportParam exportParam) {
		// 获取导出数据
		List<T> lists = Lists.newArrayList();
		if (tenantId != null) {
			lists = (List<T>) this.findAllBusi(reQueryParams, tenantId, false);
		} else {
			lists = (List<T>) this.findAll(reQueryParams);
		}

		if (lists == null || lists.size() < 1) {
			return lists;
		}

		// 导出文件
		URLUtil util = new URLUtil();
		String time = CommonUtil.getCurrTime();
		String fileName = time + ".xls";
		DateFormat format = new SimpleDateFormat("yyyyMMdd");
		String today = format.format(new Date());
		String homePath = util.getValueByName(ICommonConstants.EXPORT_PATH);
		String path = new StringBuilder(homePath).append("/").append(today)
				.append("/").append(fileName).toString();
		final List<T> exportList = lists;
		Thread t = new Thread() {
			@Override
			public void run() {
				// 构建导出参数
				File file = new File(homePath + today);
				if (!file.exists()) {
					file.mkdir();
				}
				Map<String, String> formatMap = exportParam.getFormatMap();
				Map<String, String> columnsMap = exportParam.getColumnsMap();
				if (columnsMap.size() < 1) {
					throw new BusinessException("",
							ICommonConstants.EXPORT_ERROR.COLUMN_NUM_NULL
									.lable(), "必须有导出列");
				}
				List<POIParam> params = Lists.newArrayList();
				for (Entry<String, String> column : columnsMap.entrySet()) {
					POIParam param = new POIParam();
					String colName = column.getKey();
					param.setColName(colName);
					param.setColTitle(column.getValue());
					if (formatMap.containsKey(colName)) {
						param.setFormat(formatMap.get(colName));
					}
					params.add(param);
				}

				// 保存文件导出状态为导出中,并导出
				ExportThreadParam threadParam = new ExportThreadParam(
						ExportStatusEnum.EXPORTING);
				ActionContextHolder.putExportThreadParam(time, threadParam);
				ExcelExport<T> excelExport = new ExcelExport<>(path,
						exportParam.getTitle());
				excelExport.export(exportList, params);
				// 更新文件的导出状态为已导出
				threadParam = new ExportThreadParam(ExportStatusEnum.EXPORTED);
				ActionContextHolder.putExportThreadParam(time, threadParam);
			}
		};
		t.start();
		// 构建返回值
		List<T> rtnList = Lists.newArrayList();
		T entity = lists.get(0);
		String url = new StringBuilder(today).append("/").append(fileName)
				.toString();
		entity.setUrl(url);
		rtnList.add(entity);
		return rtnList;
	}

	/**
	 * 设置分页信息
	 *
	 * @param query
	 * @param builder
	 * @param predicate
	 * @param requestParams
	 */
	public boolean setPageInfo(JPAQuery query, PathBuilder builder,
			BooleanExpression predicate, QueryParams requestParams) {
		Map<RestrictedPaginationKeys, Integer> pagintion = requestParams
				.getPagination();// 获取分页参数
		if (pagintion.size() == 0)
			return false;
		query.from(builder).where(predicate);
		int totalCount = (int) query.fetchCount();// 总条数

		if (totalCount == 0)
			return false;
		int currPage = PageInfo.getInstance().getCurrPage();// 当前页
		int pageSize = PageInfo.getInstance().getSize();// 分页条数
		int startNum = PageInfo.getInstance().getStartNum(); // 当前页开始条数
		int endNum = pageSize - 1;// 当前页结束条数
		if (pagintion.get(RestrictedPaginationKeys.number) != null) {
			currPage = pagintion.get(RestrictedPaginationKeys.number);
		}
		if (pagintion.get(RestrictedPaginationKeys.size) != null) {
			pageSize = pagintion.get(RestrictedPaginationKeys.size);
		}
		int totalPage = (totalCount + pageSize - 1) / pageSize; // 计算总页数
		if (currPage > totalPage)
			currPage = totalPage;
		startNum = pageSize * (currPage - 1) + 1;// 计算当前页开始条数
		endNum = startNum + pageSize - 1; // 计算当前页结束条数
		if (endNum > totalCount)
			endNum = totalCount;

		// 设置分页信息
		PageInfo.getInstance().setTotalCount(totalCount);
		PageInfo.getInstance().setCurrPage(currPage);
		PageInfo.getInstance().setSize(pageSize);
		PageInfo.getInstance().setTotalPage(totalPage);
		PageInfo.getInstance().setStartNum(startNum);
		PageInfo.getInstance().setEndNum(endNum);
		return true;
	}

	/**
	 * 查询参数转换
	 *
	 * @param pathBuilder
	 * @param requestParams
	 * @return
	 */
	public BooleanExpression buildPredicate(PathBuilder<?> pathBuilder,
			QueryParams requestParams) {
		// BooleanExpression result = null;
		BooleanExpression result = pathBuilder
				.getNumber("id", BigDecimal.class).goe(new BigDecimal(0));
		Iterator<String> it = requestParams.getFilters().getParams().keySet()
				.iterator();
		// ArrayList<BooleanExpression> orBeList = new
		// ArrayList<BooleanExpression>(); // 存储含或（$or）条件
		ArrayList<BooleanExpression> orBeList1 = new ArrayList<BooleanExpression>(); // 存储含或（$or1）条件组
		ArrayList<BooleanExpression> orBeList2 = new ArrayList<BooleanExpression>(); // 存储含或（$or2）条件组
		ArrayList<BooleanExpression> orBeList3 = new ArrayList<BooleanExpression>(); // 存储含或（$or3）条件组
		ArrayList<BooleanExpression> andBeList = new ArrayList<BooleanExpression>(); // 存储and条件

		// 获取参数map
		Map<String, String> keyMap = CommonUtil
				.getKeyMapByFilter(requestParams);
		Set<String> keySet = keyMap.keySet();
		for (String key : keySet) {
			String fpkey = key.replace("---" + key.substring(key.length() - 1),
					"");// 去除客户端冗余
			logger.debug("key : " + fpkey);
			logger.debug("value : " + keyMap.get(key));
			// 存储条件 key：or/and value:be
			Map<String, BooleanExpression> beMap = new HashMap<String, BooleanExpression>();
			beMap = condition(beMap, pathBuilder, fpkey, keyMap.get(key));
			if (beMap == null)
				continue;
			if (beMap.get("or1") != null) {
				orBeList1.add(beMap.get("or1"));
			}
			if (beMap.get("or2") != null) {
				orBeList2.add(beMap.get("or2"));
			}
			if (beMap.get("or3") != null) {
				orBeList3.add(beMap.get("or3"));
			}
			if (beMap.get("and") != null) {
				andBeList.add(beMap.get("and"));
			}
		}

		// 条件拼接
		for (int i = 0; i < andBeList.size(); i++) {
			result = result.and(andBeList.get(i));
		}
		// 拼接或条件
		// if(orBeList.size() > 0 ) result.and(joinCondition(orBeList));
		if (orBeList1.size() > 0)
			result = result.and(joinCondition(orBeList1));
		if (orBeList2.size() > 0)
			result = result.and(joinCondition(orBeList2));
		if (orBeList3.size() > 0)
			result = result.and(joinCondition(orBeList3));
		logger.debug(result);
		return result;
	}

	/**
	 * 或条件组拼接
	 *
	 * @param orBeList
	 * @return
	 */
	public BooleanExpression joinCondition(ArrayList<BooleanExpression> orBeList) {
		if (orBeList.size() == 0)
			return null;
		BooleanExpression orBe = orBeList.get(0);
		for (int i = 1; i < orBeList.size(); i++) {
			orBe = orBe.or(orBeList.get(i));
		}
		return orBe;
	}

	/**
	 * 获取单个条件
	 *
	 * @param beMap
	 * @param pathBuilder
	 * @param fpkey
	 * @param value
	 * @return map key：or/and value:be
	 */
	public Map<String, BooleanExpression> condition(
			Map<String, BooleanExpression> beMap, PathBuilder<?> pathBuilder,
			String fpkey, String value) {
		// String or = "$or"; //条件或
		String or1 = "$or1"; // 条件或
		String or2 = "$or2"; // 条件或
		String or3 = "$or3"; // 条件或
		BooleanExpression be = null;

		// logger.debug("fpkey:" + fpkey);
		// logger.debug("value:" + value);

		if (value == null || value.length() == 0) {
			return null;
		}

		String fpkeyOnly = fpkey;

		// 如果只包含或分组条件 去除分隔符@
		if (fpkey.split("@", -1).length > 1) {
			String str = fpkey.split("@", -1)[1];
			if (or1.equals(str) || or2.equals(str) || or3.equals(str)) {
				fpkeyOnly = fpkeyOnly.replace("@", "");
			}
		}
		fpkeyOnly = fpkeyOnly.replace(or1, "");
		fpkeyOnly = fpkeyOnly.replace(or2, "");
		fpkeyOnly = fpkeyOnly.replace(or3, "");

		if (CommonUtil.checkFieldIsSet(pathBuilder, fpkeyOnly)) {
			String pathName = fpkeyOnly.split("\\.", -1)[0];
			// 根据反射机制获取字段属性
			Field field = null;
			try {
				field = pathBuilder.getType().getDeclaredField(
						fpkeyOnly.split("\\.", -1)[0]);
				String className = null;
				// set和list的查询
				if (field.getGenericType().toString()
						.startsWith("java.util.Set")) {
					className = field.getGenericType().toString()
							.replace("java.util.Set<", "").replace(">", "");
				} else {
					className = field.getGenericType().toString()
							.replace("java.util.List<", "").replace(">", "");
				}
				Class<T> clazz = (Class<T>) Class.forName(className);
				PathBuilder<?> path = new PathBuilder(clazz, "entity"
						+ pathName);
				Path alias = new PathBuilder(clazz, pathName);
				PathBuilder<?> builder = new PathBuilder(clazz, pathName);
				pathBuilder = builder;
				fpkeyOnly = fpkeyOnly.split("\\.", -1)[1];

			} catch (Exception e) {
				logger.debug("没有找到相应字段！");
			}

		}

		// 获取be（单个条件）
		if (fpkeyOnly.indexOf("@") == -1) {
			BooleanExpression temp = compare(be, pathBuilder, fpkeyOnly, value);
			if (temp != null) {
				be = temp;// 不含运算符比较
			}
			// be = compare(be, pathBuilder, fpkeyOnly, value);// 不含运算符比较
		} else {
			be = operator(be, pathBuilder, fpkeyOnly, value); // 含运算符比较
		}

		if (fpkey.indexOf(or1) != -1) {
			beMap.put("or1", be);
		} else if (fpkey.indexOf(or2) != -1) {
			beMap.put("or2", be);
		} else if (fpkey.indexOf(or3) != -1) {
			beMap.put("or3", be);
		} else {
			beMap.put("and", be);
		}
		return beMap;
	}

	/**
	 * 不含运算符比较
	 *
	 * @param be
	 * @param pathBuilder
	 * @param fpkeyOnly
	 * @param value
	 * @return
	 */
	public BooleanExpression compare(BooleanExpression be,
			PathBuilder<?> pathBuilder, String fpkeyOnly, String value) {
		if ("healthInfoQueryType".equals(fpkeyOnly) || "flagQueryType".equals(fpkeyOnly)) {
			return null;
		}
		// 根据是否数字决定比较类型
		if (CommonUtil.checkFieldIsNumber(pathBuilder, fpkeyOnly)) {
			if (isNumber(value)) {
				be = pathBuilder.getNumber(fpkeyOnly, BigDecimal.class).eq(
						new BigDecimal(value));
			}
		} else {
			be = pathBuilder.getString(fpkeyOnly).eq(value);
		}
		return be;
	}

	/**
	 * 含运算符计算
	 *
	 * @param be
	 * @param pathBuilder
	 * @param fpkey
	 * @param value
	 * @return be
	 */
	public BooleanExpression operator(BooleanExpression be,
			PathBuilder<?> pathBuilder, String fpkey, String value) {
		String lt = "$lt"; // 小于
		String lte = "$lte"; // 小于等于
		String gt = "$gt"; // 大于
		String gte = "$gte"; // 大于等于
		String not = "$not"; // 不等于
		String like = "$like"; // 模糊查询 like %***%
		String likeAfter = "$likeAfter"; // 模糊查询 like ***%
		String isNull = "$isNull"; // 是 null
		String isNotNull = "$isNotNull"; // 不是 null
		String eq = "$eq"; // 相等
		String fpkeyOnly = fpkey.substring(0, fpkey.indexOf("@"));

		// 判断字段类型是否为int,double
		if (CommonUtil.checkFieldIsNumber(pathBuilder, fpkeyOnly)
				&& isNumber(value)) {
			// "<"比较
			if (fpkey.indexOf(lt) != -1) {
				if (fpkey.indexOf(lte) != -1) { // "<="
					be = pathBuilder.getNumber(fpkeyOnly, BigDecimal.class)
							.loe(new BigDecimal(value));
				} else {
					be = pathBuilder.getNumber(fpkeyOnly, BigDecimal.class).lt(
							new BigDecimal(value));
				}
			}
			// “>” 比较
			if (fpkey.indexOf(gt) != -1) {
				if (fpkey.indexOf(gte) != -1) { // ">="
					be = pathBuilder.getNumber(fpkeyOnly, BigDecimal.class)
							.goe(new BigDecimal(value));
				} else {
					be = pathBuilder.getNumber(fpkeyOnly, BigDecimal.class).gt(
							new BigDecimal(value));
				}
			}
			// "!="
			if (fpkey.indexOf(not) != -1) {
				be = pathBuilder.getNumber(fpkeyOnly, BigDecimal.class).ne(
						new BigDecimal(value));
			}
			// "="
			if (fpkey.indexOf(eq) != -1) {
				be = pathBuilder.getNumber(fpkeyOnly, BigDecimal.class).eq(
						new BigDecimal(value));
			}
		} else {
			// "!="
			if (fpkey.indexOf(not) != -1) {
				be = pathBuilder.getString(fpkeyOnly).ne(value);
			}

			if (fpkey.indexOf(like) != -1) {
				String str = "%" + value + "%";
				logger.debug("like:" + str);
				be = pathBuilder.getString(fpkeyOnly).like(str);
			}

			if (fpkey.indexOf(likeAfter) != -1) {
				String str = value + "%";
				logger.debug("like:" + str);
				be = pathBuilder.getString(fpkeyOnly).like(str);
			}

			// "isNull"
			if (fpkey.indexOf(isNull) != -1) {
				be = pathBuilder.getString(fpkeyOnly).isNull();
			}
			// "isNotNull"
			if (fpkey.indexOf(isNotNull) != -1) {
				be = pathBuilder.getString(fpkeyOnly).isNotNull()
						.and(pathBuilder.getString(fpkeyOnly).isNotEmpty());
			}
		}
		return be;
	}

	public static boolean isNumeric(final String str) {
		try {
			Integer.parseInt(str);
		} catch (final NumberFormatException e) {
			return false;
		}
		return true;
	}

	/**
	 * 判断字符串是否数值
	 *
	 * @param str
	 * @return true:是数值 ；false：不是数值
	 * @author:WD_SUHUAFU
	 */
	private boolean isNumber(final String str) {
		final Pattern pattern = Pattern.compile("^[0-9]+(.[0-9]*)?$");
		final Matcher match = pattern.matcher(str);
		return match.matches();
	}

	public Class<T> getEntityClass() {
		return entityClass;
	}

	@Override
	public void setEntityClass(final Class entityClass) {
		this.entityClass = entityClass;
	}

	@Override
	protected PagingAndSortingRepository getDao() {
		return new GenericDao(this.entityClass, this.em);
	}

	/**
	 * 获取排序条件
	 *
	 * @param sortMap
	 * @param builder
	 * @return ArrayList<OrderSpecifier>
	 */
	public ArrayList<OrderSpecifier> getOrderSpecifiers(
			Map<String, SortingParams> sortMap, PathBuilder<?> builder) {
		ArrayList<OrderSpecifier> orderSpecifiers = new ArrayList<OrderSpecifier>();
		Set<String> keySet = sortMap.keySet();
		String keyTemp;
		for (String key : keySet) {
			keyTemp = key;
			String paramT = sortMap.get(key).getParams().toString()
					.replace("{", "").replace("}", "");
			String paramTemp[] = paramT.split(",");// huibati 同entity下可能有多个条件
			for (String param : paramTemp) {
				String fkey = param.substring(0, param.indexOf("="));
				if (!"".equals(fkey))
					key = keyTemp + "." + fkey;
				param = param.substring(param.indexOf("=") + 1, param.length());
				if ("asc".equals(param)) {
					orderSpecifiers.add(new OrderSpecifier(Order.ASC, builder
							.get(key)));
				}
				if ("desc".equals(param)) {
					orderSpecifiers.add(new OrderSpecifier(Order.DESC, builder
							.get(key)));
				}
			}
		}
		return orderSpecifiers;
	}

	/**
	 * 获取joinPath
	 *
	 * @param pathBuilder
	 * @param requestParams
	 * @return
	 */
	public ArrayList<String> getJoinCloumn(PathBuilder pathBuilder,
			QueryParams requestParams) {
		ArrayList<String> arrayList = new ArrayList<String>();
		// 获取参数map
		Map<String, String> keyMap = CommonUtil
				.getKeyMapByFilter(requestParams);
		Set<String> keySet = keyMap.keySet();
		for (String key : keySet) {
			// 判断是否是多对多
			if (key.split("@", -1).length > 1) {
				key = key.split("@", -1)[0];
			}
			if (CommonUtil.checkFieldIsSet(pathBuilder, key)) {
				arrayList.add(key.split("\\.", -1)[0]);
			}
		}

		// 支持include方式，客户端定义include，则此处需要加入join的关联带出
		TypedParams<IncludedRelationsParams> includedParams = requestParams
				.getIncludedRelations();
		Map<String, IncludedRelationsParams> includedMap = includedParams
				.getParams();
		Set<String> includeKeySet = includedMap.keySet();
		for (String includedKey : includeKeySet) {
			IncludedRelationsParams includedRelationsParams = includedMap
					.get(includedKey);
			if (includedRelationsParams != null) {
				for (Inclusion inclusion : includedRelationsParams.getParams()) {
					if (!arrayList.contains(inclusion.getPath())) {
						arrayList.add(inclusion.getPath());
					}

				}
			}
		}
		return arrayList;
	}

}
